Initialization and import of data

install.packages("tidyverse")
essai de l'URL 'https://cran.rstudio.com/bin/macosx/contrib/4.0/tidyverse_1.3.0.tgz'
Content type 'application/x-gzip' length 433049 bytes (422 KB)
==================================================
downloaded 422 KB

The downloaded binary packages are in
    /var/folders/6g/jj4zrn8n0pv9nvlgqdvg6k500000gn/T//RtmpudGAN7/downloaded_packages
install.packages("pacman")
Error in install.packages : Updating loaded packages
install.packages("dplyr")
essai de l'URL 'https://cran.rstudio.com/bin/macosx/contrib/4.0/dplyr_1.0.5.tgz'
Content type 'application/x-gzip' length 1251016 bytes (1.2 MB)
==================================================
downloaded 1.2 MB

The downloaded binary packages are in
    /var/folders/6g/jj4zrn8n0pv9nvlgqdvg6k500000gn/T//RtmpudGAN7/downloaded_packages
install.packages("plotly")
essai de l'URL 'https://cran.rstudio.com/bin/macosx/contrib/4.0/plotly_4.9.3.tgz'
Content type 'application/x-gzip' length 3063060 bytes (2.9 MB)
==================================================
downloaded 2.9 MB

The downloaded binary packages are in
    /var/folders/6g/jj4zrn8n0pv9nvlgqdvg6k500000gn/T//RtmpudGAN7/downloaded_packages
install.packages("pacman")
essai de l'URL 'https://cran.rstudio.com/bin/macosx/contrib/4.0/pacman_0.5.1.tgz'
Content type 'application/x-gzip' length 379950 bytes (371 KB)
==================================================
downloaded 371 KB

The downloaded binary packages are in
    /var/folders/6g/jj4zrn8n0pv9nvlgqdvg6k500000gn/T//RtmpudGAN7/downloaded_packages
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.0 ──
✓ ggplot2 3.3.3     ✓ purrr   0.3.4
✓ tibble  3.1.0     ✓ dplyr   1.0.5
✓ tidyr   1.1.3     ✓ stringr 1.4.0
✓ readr   1.4.0     ✓ forcats 0.5.1
── Conflicts ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
fig <- function(width, heigth){
     options(repr.plot.width = width, repr.plot.height = heigth)
}

library(pacman)

pacman::p_load(pacman,dplyr, ggplot2, rio, gridExtra, scales, ggcorrplot, caret, e1071)

dataSet <- read.csv('data/train.csv')
names(dataSet)
 [1] "battery_power" "blue"          "clock_speed"   "dual_sim"      "fc"            "four_g"        "int_memory"    "m_dep"         "mobile_wt"     "n_cores"       "pc"           
[12] "px_height"     "px_width"      "ram"           "sc_h"          "sc_w"          "talk_time"     "three_g"       "touch_screen"  "wifi"          "price_range"  

Display of the set of data.

Columns : battery_power, blue, clock_speed, dual_sim, fc, four_g,int_memory, m_dep, mobile_wt, n_cores, pc, px_height, px_width, ram, sc_h, sc_w, talk_time, three_g, touch_screen, wifi, price_range

battery_power:Total energy a battery can store in one time measured in mAh blue:Has bluetooth or not clock_speed:speed at which microprocessor executes instructions dual_sim:Has dual sim support or not fc:Front Camera mega pixels four_g:Has 4G or not int_memory:Internal Memory in Gigabytes m_dep:Mobile Depth in cm mobile_wt:Weight of mobile phone n_cores:Number of cores of processor pc:Primary Camera mega pixels px_height:Pixel Resolution Height px_width:Pixel Resolution Width ram:Random Access Memory in Megabytes sc_h:Screen Height of mobile in cm sc_w:Screen Width of mobile in cm talk_time:longest time that a single battery charge will last when you are three_g:Has 3G or not touch_screen:Has touch screen or not wifi:Has wifi or not price_range: This is the target variable with value of 0(low cost), 1(medium cost), 2(high cost) and 3(very high cost).

dim(dataSet)
[1] 2000   21
class(dataSet)
[1] "data.frame"
head(dataSet)
sapply(dataSet, class)
battery_power          blue   clock_speed      dual_sim            fc        four_g    int_memory         m_dep     mobile_wt       n_cores            pc     px_height      px_width 
    "integer"     "integer"     "numeric"     "integer"     "integer"     "integer"     "integer"     "numeric"     "integer"     "integer"     "integer"     "integer"     "integer" 
          ram          sc_h          sc_w     talk_time       three_g  touch_screen          wifi   price_range 
    "integer"     "integer"     "integer"     "integer"     "integer"     "integer"     "integer"     "integer" 
summary(dataSet)
 battery_power         blue        clock_speed       dual_sim            fc             four_g         int_memory        m_dep          mobile_wt        n_cores            pc        
 Min.   : 501.0   Min.   :0.000   Min.   :0.500   Min.   :0.0000   Min.   : 0.000   Min.   :0.0000   Min.   : 2.00   Min.   :0.1000   Min.   : 80.0   Min.   :1.000   Min.   : 0.000  
 1st Qu.: 851.8   1st Qu.:0.000   1st Qu.:0.700   1st Qu.:0.0000   1st Qu.: 1.000   1st Qu.:0.0000   1st Qu.:16.00   1st Qu.:0.2000   1st Qu.:109.0   1st Qu.:3.000   1st Qu.: 5.000  
 Median :1226.0   Median :0.000   Median :1.500   Median :1.0000   Median : 3.000   Median :1.0000   Median :32.00   Median :0.5000   Median :141.0   Median :4.000   Median :10.000  
 Mean   :1238.5   Mean   :0.495   Mean   :1.522   Mean   :0.5095   Mean   : 4.309   Mean   :0.5215   Mean   :32.05   Mean   :0.5018   Mean   :140.2   Mean   :4.521   Mean   : 9.916  
 3rd Qu.:1615.2   3rd Qu.:1.000   3rd Qu.:2.200   3rd Qu.:1.0000   3rd Qu.: 7.000   3rd Qu.:1.0000   3rd Qu.:48.00   3rd Qu.:0.8000   3rd Qu.:170.0   3rd Qu.:7.000   3rd Qu.:15.000  
 Max.   :1998.0   Max.   :1.000   Max.   :3.000   Max.   :1.0000   Max.   :19.000   Max.   :1.0000   Max.   :64.00   Max.   :1.0000   Max.   :200.0   Max.   :8.000   Max.   :20.000  
   px_height         px_width           ram            sc_h            sc_w          talk_time        three_g        touch_screen        wifi        price_range  
 Min.   :   0.0   Min.   : 500.0   Min.   : 256   Min.   : 5.00   Min.   : 0.000   Min.   : 2.00   Min.   :0.0000   Min.   :0.000   Min.   :0.000   Min.   :0.00  
 1st Qu.: 282.8   1st Qu.: 874.8   1st Qu.:1208   1st Qu.: 9.00   1st Qu.: 2.000   1st Qu.: 6.00   1st Qu.:1.0000   1st Qu.:0.000   1st Qu.:0.000   1st Qu.:0.75  
 Median : 564.0   Median :1247.0   Median :2146   Median :12.00   Median : 5.000   Median :11.00   Median :1.0000   Median :1.000   Median :1.000   Median :1.50  
 Mean   : 645.1   Mean   :1251.5   Mean   :2124   Mean   :12.31   Mean   : 5.767   Mean   :11.01   Mean   :0.7615   Mean   :0.503   Mean   :0.507   Mean   :1.50  
 3rd Qu.: 947.2   3rd Qu.:1633.0   3rd Qu.:3064   3rd Qu.:16.00   3rd Qu.: 9.000   3rd Qu.:16.00   3rd Qu.:1.0000   3rd Qu.:1.000   3rd Qu.:1.000   3rd Qu.:2.25  
 Max.   :1960.0   Max.   :1998.0   Max.   :3998   Max.   :19.00   Max.   :18.000   Max.   :20.00   Max.   :1.0000   Max.   :1.000   Max.   :1.000   Max.   :3.00  
df <- data.frame(
  group = c(0, 1, 2, 3),
  value = c(sum(dataSet$price_range==0), sum(dataSet$price_range==1), sum(dataSet$price_range==2), sum(dataSet$price_range==3))
  )
bp<- ggplot(df, aes(x="", y=value, fill=group))+
geom_bar(width = 1, stat = "identity")
bp

pie <- bp + coord_polar("y", start=0)
pie

fig(18, 16)

Correlation plot showing the features that are the most linked between each others

library(ggcorrplot)
corr <- round(cor(dataSet), 8)
ggcorrplot(corr)

fig(18, 16)
str(dataSet)
'data.frame':   2000 obs. of  21 variables:
 $ battery_power: int  842 1021 563 615 1821 1859 1821 1954 1445 509 ...
 $ blue         : int  0 1 1 1 1 0 0 0 1 1 ...
 $ clock_speed  : num  2.2 0.5 0.5 2.5 1.2 0.5 1.7 0.5 0.5 0.6 ...
 $ dual_sim     : int  0 1 1 0 0 1 0 1 0 1 ...
 $ fc           : int  1 0 2 0 13 3 4 0 0 2 ...
 $ four_g       : int  0 1 1 0 1 0 1 0 0 1 ...
 $ int_memory   : int  7 53 41 10 44 22 10 24 53 9 ...
 $ m_dep        : num  0.6 0.7 0.9 0.8 0.6 0.7 0.8 0.8 0.7 0.1 ...
 $ mobile_wt    : int  188 136 145 131 141 164 139 187 174 93 ...
 $ n_cores      : int  2 3 5 6 2 1 8 4 7 5 ...
 $ pc           : int  2 6 6 9 14 7 10 0 14 15 ...
 $ px_height    : int  20 905 1263 1216 1208 1004 381 512 386 1137 ...
 $ px_width     : int  756 1988 1716 1786 1212 1654 1018 1149 836 1224 ...
 $ ram          : int  2549 2631 2603 2769 1411 1067 3220 700 1099 513 ...
 $ sc_h         : int  9 17 11 16 8 17 13 16 17 19 ...
 $ sc_w         : int  7 3 2 8 2 1 8 3 1 10 ...
 $ talk_time    : int  19 7 9 11 15 10 18 5 20 12 ...
 $ three_g      : int  0 1 1 1 1 1 1 1 1 1 ...
 $ touch_screen : int  0 1 1 0 1 0 0 1 0 0 ...
 $ wifi         : int  1 0 0 0 0 0 1 1 0 0 ...
 $ price_range  : int  1 2 2 2 1 1 3 0 0 0 ...

Displaying the cell percentages of different features of the dataSet

prop.table(table(dataSet$blue)) # cell percentages

    0     1 
0.505 0.495 
prop.table(table(dataSet$dual_sim)) # cell percentages

     0      1 
0.4905 0.5095 
prop.table(table(dataSet$four_g)) # cell percentages

     0      1 
0.4785 0.5215 
prop.table(table(dataSet$three_g)) # cell percentages

     0      1 
0.2385 0.7615 
prop.table(table(dataSet$touch_screen)) # cell percentages

    0     1 
0.497 0.503 
prop.table(table(dataSet$wifi)) # cell percentages

    0     1 
0.493 0.507 

Subplots using filtered dataSet showing the impact of the screen height and width on the mobile’s price range

library(ggplot2)
data = data.frame(Dimensions_in_cm = c(dataSet$sc_h, dataSet$sc_w), 
               Screen = rep(c("Height", "Width"), c(length(dataSet$sc_h), length(dataSet$sc_w))))
ggplot(data, aes(Dimensions_in_cm, fill = Screen)) + 
  geom_bar(position = 'identity', alpha = .6)

Comparing the impact of two features on the mobile’s price range

library(ggplot2)
library(gridExtra)
dataSet$price_range <- as.factor(dataSet$price_range)
p1 <-  ggplot(dataSet, aes(x=px_width, y = px_height, color=price_range)) +
  geom_boxplot(outlier.colour="red", outlier.shape=8,
               outlier.size=4) +
  labs(title = "Pixel Resolution Height vs Pixel Resolution Width")
p2 <- ggplot(dataSet, aes(x=price_range, y = ram, color=price_range)) +
  geom_boxplot(outlier.colour="red", outlier.shape=8,
               outlier.size=4) +
  labs(title = "RAM vs Price Range")
grid.arrange(p1, p2,nrow = 1)

fig(24, 20)

Comparing the impact of two features on the mobile’s price range

library(ggplot2)
library(gridExtra)
dataSet$price_range <- as.factor(dataSet$price_range)
p3 <- ggplot(dataSet, aes(x=price_range, y = int_memory, color=price_range)) +
  geom_boxplot(outlier.colour="red", outlier.shape=8,
               outlier.size=4) +
  labs(title = "int_memory vs Price Range")
p4 <- ggplot(dataSet, aes(x=price_range, y = battery_power, color=price_range)) +
  geom_boxplot(outlier.colour="red", outlier.shape=8,
               outlier.size=4) +
  labs(title = "Battery power vs Price Range")
grid.arrange(p3, p4,nrow = 1)

fig(24, 20)

Interquartile range of two features at a time

library(dplyr)
library(ggplot2)
library(gridExtra)
#Battery_power IQR
firstQuantile <- quantile(dataSet$battery_power, 0.25)
thirdQuantile <- quantile(dataSet$battery_power, 0.75)
battery_powerIQR <- dataSet %>% filter(dataSet$battery_power > firstQuantile & dataSet$battery_power < thirdQuantile)
#Int Memory IQR
firstQuantile <- quantile(dataSet$int_memory , 0.25)
thirdQuantile <- quantile(dataSet$int_memory, 0.75)
int_memoryIQR <- dataSet %>% filter(dataSet$int_memory > firstQuantile & dataSet$int_memory < thirdQuantile)
#ram IQR
firstQuantile <- quantile(dataSet$ram , 0.25)
thirdQuantile <- quantile(dataSet$ram, 0.75)
ramIQR <- dataSet %>% filter(dataSet$ram > firstQuantile & dataSet$ram < thirdQuantile)

p2 <- ggplot(ramIQR, aes(x=price_range, y = ram, color=price_range)) +
  geom_boxplot(outlier.colour="red", outlier.shape=8,
               outlier.size=4) +
  labs(title = "IQR RAM vs Price Range")

p3 <- ggplot(int_memoryIQR, aes(x=price_range, y = int_memory, color=price_range)) +
  geom_boxplot(outlier.colour="red", outlier.shape=8,
               outlier.size=4) +
  labs(title = "IQR int memory vs Price Range")

p4 <- ggplot(battery_powerIQR, aes(x=price_range, y = battery_power, color=price_range)) +
  geom_boxplot(outlier.colour="red", outlier.shape=8,
               outlier.size=4) +
  labs(title = "IQR battery power vs Price Range")
grid.arrange(p2, p3, p4,nrow = 1)

fig(24, 20)

Data classification depending on battery power, ram, memory, clock speed and number of cores

library(ggplot2)
p <- ggplot(dataSet, aes(battery_power, ram, color = price_range))+
  geom_point()
p + stat_ellipse()

p <- ggplot(dataSet, aes(int_memory, ram, color = price_range))+
  geom_point()
p + stat_ellipse()

3D graphic

library(tidyverse)
library(plotly)
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attachement du package : ‘plotly’

The following object is masked from ‘package:rio’:

    export

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
# Creating the graphic
p <- plot_ly(
  dataSet, x = dataSet$battery_power, y = dataSet$ram, z = dataSet$int_memory, 
  color = dataSet$price_range) %>%
  add_markers(size=1) %>%
  layout(
    scene = list(xaxis = list(title = 'Battery Power'),
        yaxis = list(title = 'Ram'),
        zaxis = list(title = 'Memoire interne'))
        )
p
LS0tCnRpdGxlOiAiQW5hbHl6aW5nIERhdGEgU2V0IE1vYmlsZSBQcmljZSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKSW5pdGlhbGl6YXRpb24gYW5kIGltcG9ydCBvZiBkYXRhCgpgYGB7cn0KaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikKaW5zdGFsbC5wYWNrYWdlcygicGFjbWFuIikKaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQppbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQoKbGlicmFyeSh0aWR5dmVyc2UpCgpmaWcgPC0gZnVuY3Rpb24od2lkdGgsIGhlaWd0aCl7CiAgICAgb3B0aW9ucyhyZXByLnBsb3Qud2lkdGggPSB3aWR0aCwgcmVwci5wbG90LmhlaWdodCA9IGhlaWd0aCkKfQoKbGlicmFyeShwYWNtYW4pCgpwYWNtYW46OnBfbG9hZChwYWNtYW4sZHBseXIsIGdncGxvdDIsIHJpbywgZ3JpZEV4dHJhLCBzY2FsZXMsIGdnY29ycnBsb3QsIGNhcmV0LCBlMTA3MSkKCmRhdGFTZXQgPC0gcmVhZC5jc3YoJ2RhdGEvdHJhaW4uY3N2JykKYGBgCgoKYGBge3J9Cm5hbWVzKGRhdGFTZXQpCmBgYAoKRGlzcGxheSBvZiB0aGUgc2V0IG9mIGRhdGEuCgpDb2x1bW5zIDogYmF0dGVyeV9wb3dlciwgYmx1ZSwgY2xvY2tfc3BlZWQsIGR1YWxfc2ltLCBmYywgZm91cl9nLGludF9tZW1vcnksIG1fZGVwLCBtb2JpbGVfd3QsIG5fY29yZXMsIHBjLCBweF9oZWlnaHQsIHB4X3dpZHRoLCByYW0sIHNjX2gsIHNjX3csIHRhbGtfdGltZSwgdGhyZWVfZywgdG91Y2hfc2NyZWVuLCB3aWZpLCBwcmljZV9yYW5nZQoKYmF0dGVyeV9wb3dlcjpUb3RhbCBlbmVyZ3kgYSBiYXR0ZXJ5IGNhbiBzdG9yZSBpbiBvbmUgdGltZSBtZWFzdXJlZCBpbiBtQWgKYmx1ZTpIYXMgYmx1ZXRvb3RoIG9yIG5vdApjbG9ja19zcGVlZDpzcGVlZCBhdCB3aGljaCBtaWNyb3Byb2Nlc3NvciBleGVjdXRlcyBpbnN0cnVjdGlvbnMKZHVhbF9zaW06SGFzIGR1YWwgc2ltIHN1cHBvcnQgb3Igbm90CmZjOkZyb250IENhbWVyYSBtZWdhIHBpeGVscwpmb3VyX2c6SGFzIDRHIG9yIG5vdAppbnRfbWVtb3J5OkludGVybmFsIE1lbW9yeSBpbiBHaWdhYnl0ZXMKbV9kZXA6TW9iaWxlIERlcHRoIGluIGNtCm1vYmlsZV93dDpXZWlnaHQgb2YgbW9iaWxlIHBob25lCm5fY29yZXM6TnVtYmVyIG9mIGNvcmVzIG9mIHByb2Nlc3NvcgpwYzpQcmltYXJ5IENhbWVyYSBtZWdhIHBpeGVscwpweF9oZWlnaHQ6UGl4ZWwgUmVzb2x1dGlvbiBIZWlnaHQKcHhfd2lkdGg6UGl4ZWwgUmVzb2x1dGlvbiBXaWR0aApyYW06UmFuZG9tIEFjY2VzcyBNZW1vcnkgaW4gTWVnYWJ5dGVzCnNjX2g6U2NyZWVuIEhlaWdodCBvZiBtb2JpbGUgaW4gY20Kc2NfdzpTY3JlZW4gV2lkdGggb2YgbW9iaWxlIGluIGNtCnRhbGtfdGltZTpsb25nZXN0IHRpbWUgdGhhdCBhIHNpbmdsZSBiYXR0ZXJ5IGNoYXJnZSB3aWxsIGxhc3Qgd2hlbiB5b3UgYXJlCnRocmVlX2c6SGFzIDNHIG9yIG5vdAp0b3VjaF9zY3JlZW46SGFzIHRvdWNoIHNjcmVlbiBvciBub3QKd2lmaTpIYXMgd2lmaSBvciBub3QKcHJpY2VfcmFuZ2U6IFRoaXMgaXMgdGhlIHRhcmdldCB2YXJpYWJsZSB3aXRoIHZhbHVlIG9mIDAobG93IGNvc3QpLCAxKG1lZGl1bSBjb3N0KSwgMihoaWdoIGNvc3QpIGFuZCAzKHZlcnkgaGlnaCBjb3N0KS4KCmBgYHtyfQpkaW0oZGF0YVNldCkKY2xhc3MoZGF0YVNldCkKaGVhZChkYXRhU2V0KQpzYXBwbHkoZGF0YVNldCwgY2xhc3MpCmBgYAoKCmBgYHtyfQpzdW1tYXJ5KGRhdGFTZXQpCmBgYAoKYGBge3J9CmRmIDwtIGRhdGEuZnJhbWUoCiAgZ3JvdXAgPSBjKDAsIDEsIDIsIDMpLAogIHZhbHVlID0gYyhzdW0oZGF0YVNldCRwcmljZV9yYW5nZT09MCksIHN1bShkYXRhU2V0JHByaWNlX3JhbmdlPT0xKSwgc3VtKGRhdGFTZXQkcHJpY2VfcmFuZ2U9PTIpLCBzdW0oZGF0YVNldCRwcmljZV9yYW5nZT09MykpCiAgKQpicDwtIGdncGxvdChkZiwgYWVzKHg9IiIsIHk9dmFsdWUsIGZpbGw9Z3JvdXApKSsKZ2VvbV9iYXIod2lkdGggPSAxLCBzdGF0ID0gImlkZW50aXR5IikKYnAKcGllIDwtIGJwICsgY29vcmRfcG9sYXIoInkiLCBzdGFydD0wKQpwaWUKZmlnKDE4LCAxNikKYGBgCgpDb3JyZWxhdGlvbiBwbG90IHNob3dpbmcgdGhlIGZlYXR1cmVzIHRoYXQgYXJlIHRoZSBtb3N0IGxpbmtlZCBiZXR3ZWVuIGVhY2ggb3RoZXJzCmBgYHtyfQpsaWJyYXJ5KGdnY29ycnBsb3QpCmNvcnIgPC0gcm91bmQoY29yKGRhdGFTZXQpLCA4KQpnZ2NvcnJwbG90KGNvcnIpCmZpZygxOCwgMTYpCmBgYAoKCmBgYHtyfQpzdHIoZGF0YVNldCkKYGBgCgpEaXNwbGF5aW5nIHRoZSBjZWxsIHBlcmNlbnRhZ2VzIG9mIGRpZmZlcmVudCBmZWF0dXJlcyBvZiB0aGUgZGF0YVNldApgYGB7cn0KcHJvcC50YWJsZSh0YWJsZShkYXRhU2V0JGJsdWUpKSAjIGNlbGwgcGVyY2VudGFnZXMKcHJvcC50YWJsZSh0YWJsZShkYXRhU2V0JGR1YWxfc2ltKSkgIyBjZWxsIHBlcmNlbnRhZ2VzCnByb3AudGFibGUodGFibGUoZGF0YVNldCRmb3VyX2cpKSAjIGNlbGwgcGVyY2VudGFnZXMKcHJvcC50YWJsZSh0YWJsZShkYXRhU2V0JHRocmVlX2cpKSAjIGNlbGwgcGVyY2VudGFnZXMKcHJvcC50YWJsZSh0YWJsZShkYXRhU2V0JHRvdWNoX3NjcmVlbikpICMgY2VsbCBwZXJjZW50YWdlcwpwcm9wLnRhYmxlKHRhYmxlKGRhdGFTZXQkd2lmaSkpICMgY2VsbCBwZXJjZW50YWdlcwpgYGAKCgpTdWJwbG90cyB1c2luZyBmaWx0ZXJlZCBkYXRhU2V0IHNob3dpbmcgdGhlIGltcGFjdCBvZiB0aGUgc2NyZWVuIGhlaWdodCBhbmQgd2lkdGggb24gdGhlIG1vYmlsZSdzIHByaWNlIHJhbmdlCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmRhdGEgPSBkYXRhLmZyYW1lKERpbWVuc2lvbnNfaW5fY20gPSBjKGRhdGFTZXQkc2NfaCwgZGF0YVNldCRzY193KSwgCiAgICAgICAgICAgICAgIFNjcmVlbiA9IHJlcChjKCJIZWlnaHQiLCAiV2lkdGgiKSwgYyhsZW5ndGgoZGF0YVNldCRzY19oKSwgbGVuZ3RoKGRhdGFTZXQkc2NfdykpKSkKZ2dwbG90KGRhdGEsIGFlcyhEaW1lbnNpb25zX2luX2NtLCBmaWxsID0gU2NyZWVuKSkgKyAKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICdpZGVudGl0eScsIGFscGhhID0gLjYpCmBgYAoKQ29tcGFyaW5nIHRoZSBpbXBhY3Qgb2YgdHdvIGZlYXR1cmVzIG9uIHRoZSBtb2JpbGUncyBwcmljZSByYW5nZQpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdyaWRFeHRyYSkKZGF0YVNldCRwcmljZV9yYW5nZSA8LSBhcy5mYWN0b3IoZGF0YVNldCRwcmljZV9yYW5nZSkKcDEgPC0gIGdncGxvdChkYXRhU2V0LCBhZXMoeD1weF93aWR0aCwgeSA9IHB4X2hlaWdodCwgY29sb3I9cHJpY2VfcmFuZ2UpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyPSJyZWQiLCBvdXRsaWVyLnNoYXBlPTgsCiAgICAgICAgICAgICAgIG91dGxpZXIuc2l6ZT00KSArCiAgbGFicyh0aXRsZSA9ICJQaXhlbCBSZXNvbHV0aW9uIEhlaWdodCB2cyBQaXhlbCBSZXNvbHV0aW9uIFdpZHRoIikKcDIgPC0gZ2dwbG90KGRhdGFTZXQsIGFlcyh4PXByaWNlX3JhbmdlLCB5ID0gcmFtLCBjb2xvcj1wcmljZV9yYW5nZSkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXI9InJlZCIsIG91dGxpZXIuc2hhcGU9OCwKICAgICAgICAgICAgICAgb3V0bGllci5zaXplPTQpICsKICBsYWJzKHRpdGxlID0gIlJBTSB2cyBQcmljZSBSYW5nZSIpCmdyaWQuYXJyYW5nZShwMSwgcDIsbnJvdyA9IDEpCmZpZygyNCwgMjApCmBgYAoKQ29tcGFyaW5nIHRoZSBpbXBhY3Qgb2YgdHdvIGZlYXR1cmVzIG9uIHRoZSBtb2JpbGUncyBwcmljZSByYW5nZQpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdyaWRFeHRyYSkKZGF0YVNldCRwcmljZV9yYW5nZSA8LSBhcy5mYWN0b3IoZGF0YVNldCRwcmljZV9yYW5nZSkKcDMgPC0gZ2dwbG90KGRhdGFTZXQsIGFlcyh4PXByaWNlX3JhbmdlLCB5ID0gaW50X21lbW9yeSwgY29sb3I9cHJpY2VfcmFuZ2UpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyPSJyZWQiLCBvdXRsaWVyLnNoYXBlPTgsCiAgICAgICAgICAgICAgIG91dGxpZXIuc2l6ZT00KSArCiAgbGFicyh0aXRsZSA9ICJpbnRfbWVtb3J5IHZzIFByaWNlIFJhbmdlIikKcDQgPC0gZ2dwbG90KGRhdGFTZXQsIGFlcyh4PXByaWNlX3JhbmdlLCB5ID0gYmF0dGVyeV9wb3dlciwgY29sb3I9cHJpY2VfcmFuZ2UpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyPSJyZWQiLCBvdXRsaWVyLnNoYXBlPTgsCiAgICAgICAgICAgICAgIG91dGxpZXIuc2l6ZT00KSArCiAgbGFicyh0aXRsZSA9ICJCYXR0ZXJ5IHBvd2VyIHZzIFByaWNlIFJhbmdlIikKZ3JpZC5hcnJhbmdlKHAzLCBwNCxucm93ID0gMSkKZmlnKDI0LCAyMCkKYGBgCgpJbnRlcnF1YXJ0aWxlIHJhbmdlIG9mIHR3byBmZWF0dXJlcyBhdCBhIHRpbWUKYGBge3J9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShncmlkRXh0cmEpCiNCYXR0ZXJ5X3Bvd2VyIElRUgpmaXJzdFF1YW50aWxlIDwtIHF1YW50aWxlKGRhdGFTZXQkYmF0dGVyeV9wb3dlciwgMC4yNSkKdGhpcmRRdWFudGlsZSA8LSBxdWFudGlsZShkYXRhU2V0JGJhdHRlcnlfcG93ZXIsIDAuNzUpCmJhdHRlcnlfcG93ZXJJUVIgPC0gZGF0YVNldCAlPiUgZmlsdGVyKGRhdGFTZXQkYmF0dGVyeV9wb3dlciA+IGZpcnN0UXVhbnRpbGUgJiBkYXRhU2V0JGJhdHRlcnlfcG93ZXIgPCB0aGlyZFF1YW50aWxlKQojSW50IE1lbW9yeSBJUVIKZmlyc3RRdWFudGlsZSA8LSBxdWFudGlsZShkYXRhU2V0JGludF9tZW1vcnkgLCAwLjI1KQp0aGlyZFF1YW50aWxlIDwtIHF1YW50aWxlKGRhdGFTZXQkaW50X21lbW9yeSwgMC43NSkKaW50X21lbW9yeUlRUiA8LSBkYXRhU2V0ICU+JSBmaWx0ZXIoZGF0YVNldCRpbnRfbWVtb3J5ID4gZmlyc3RRdWFudGlsZSAmIGRhdGFTZXQkaW50X21lbW9yeSA8IHRoaXJkUXVhbnRpbGUpCiNyYW0gSVFSCmZpcnN0UXVhbnRpbGUgPC0gcXVhbnRpbGUoZGF0YVNldCRyYW0gLCAwLjI1KQp0aGlyZFF1YW50aWxlIDwtIHF1YW50aWxlKGRhdGFTZXQkcmFtLCAwLjc1KQpyYW1JUVIgPC0gZGF0YVNldCAlPiUgZmlsdGVyKGRhdGFTZXQkcmFtID4gZmlyc3RRdWFudGlsZSAmIGRhdGFTZXQkcmFtIDwgdGhpcmRRdWFudGlsZSkKCnAyIDwtIGdncGxvdChyYW1JUVIsIGFlcyh4PXByaWNlX3JhbmdlLCB5ID0gcmFtLCBjb2xvcj1wcmljZV9yYW5nZSkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXI9InJlZCIsIG91dGxpZXIuc2hhcGU9OCwKICAgICAgICAgICAgICAgb3V0bGllci5zaXplPTQpICsKICBsYWJzKHRpdGxlID0gIklRUiBSQU0gdnMgUHJpY2UgUmFuZ2UiKQoKcDMgPC0gZ2dwbG90KGludF9tZW1vcnlJUVIsIGFlcyh4PXByaWNlX3JhbmdlLCB5ID0gaW50X21lbW9yeSwgY29sb3I9cHJpY2VfcmFuZ2UpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyPSJyZWQiLCBvdXRsaWVyLnNoYXBlPTgsCiAgICAgICAgICAgICAgIG91dGxpZXIuc2l6ZT00KSArCiAgbGFicyh0aXRsZSA9ICJJUVIgaW50IG1lbW9yeSB2cyBQcmljZSBSYW5nZSIpCgpwNCA8LSBnZ3Bsb3QoYmF0dGVyeV9wb3dlcklRUiwgYWVzKHg9cHJpY2VfcmFuZ2UsIHkgPSBiYXR0ZXJ5X3Bvd2VyLCBjb2xvcj1wcmljZV9yYW5nZSkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5jb2xvdXI9InJlZCIsIG91dGxpZXIuc2hhcGU9OCwKICAgICAgICAgICAgICAgb3V0bGllci5zaXplPTQpICsKICBsYWJzKHRpdGxlID0gIklRUiBiYXR0ZXJ5IHBvd2VyIHZzIFByaWNlIFJhbmdlIikKZ3JpZC5hcnJhbmdlKHAyLCBwMywgcDQsbnJvdyA9IDEpCmZpZygyNCwgMjApCmBgYAoKRGF0YSBjbGFzc2lmaWNhdGlvbiBkZXBlbmRpbmcgb24gYmF0dGVyeSBwb3dlciwgcmFtLCBtZW1vcnksIGNsb2NrIHNwZWVkIGFuZCBudW1iZXIgb2YgY29yZXMKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKcCA8LSBnZ3Bsb3QoZGF0YVNldCwgYWVzKGJhdHRlcnlfcG93ZXIsIHJhbSwgY29sb3IgPSBwcmljZV9yYW5nZSkpKwogIGdlb21fcG9pbnQoKQpwICsgc3RhdF9lbGxpcHNlKCkKcCA8LSBnZ3Bsb3QoZGF0YVNldCwgYWVzKGludF9tZW1vcnksIHJhbSwgY29sb3IgPSBwcmljZV9yYW5nZSkpKwogIGdlb21fcG9pbnQoKQpwICsgc3RhdF9lbGxpcHNlKCkKYGBgCgoKM0QgZ3JhcGhpYyAKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHBsb3RseSkKCiMgQ3JlYXRpbmcgdGhlIGdyYXBoaWMKcCA8LSBwbG90X2x5KAogIGRhdGFTZXQsIHggPSBkYXRhU2V0JGJhdHRlcnlfcG93ZXIsIHkgPSBkYXRhU2V0JHJhbSwgeiA9IGRhdGFTZXQkaW50X21lbW9yeSwgCiAgY29sb3IgPSBkYXRhU2V0JHByaWNlX3JhbmdlKSAlPiUKICBhZGRfbWFya2VycyhzaXplPTEpICU+JQogIGxheW91dCgKICAgIHNjZW5lID0gbGlzdCh4YXhpcyA9IGxpc3QodGl0bGUgPSAnQmF0dGVyeSBQb3dlcicpLAogICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICdSYW0nKSwKICAgICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSAnTWVtb2lyZSBpbnRlcm5lJykpCiAgICAgICAgKQpwCmBgYA==